package org.netty.im.config;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;

@Configuration
@MapperScan(basePackages = "org.netty.im.mapper", sqlSessionTemplateRef = "sqlSessionTemplate")
public class MyBatisConfig {

	@Value("${im.datasource.url}")
	private String sprUrl;

	@Value("${im.datasource.username}")
	private String sprUser = "clouddbusertest";

	@Value("${im.datasource.password}")
	private String sprPassword = "123456";

	@Value("${im.datasource.driverClassName}")
	private String sprDriverClass;

	@Value("${spring.druid.datasource.initialSize}")
	private int initialSize;

	@Value("${spring.druid.datasource.minIdle}")
	private int minIdle;

	@Value("${spring.druid.datasource.maxActive}")
	private int maxActive;

	@Value("${spring.druid.datasource.maxWait}")
	private int maxWait;

	@Value("${spring.druid.datasource.timeBetweenEvictionRunsMillis}")
	private int timeBetweenEvictionRunsMillis;

	@Value("${spring.druid.datasource.minEvictableIdleTimeMillis}")
	private int minEvictableIdleTimeMillis;

	@Value("${spring.druid.datasource.validationQuery}")
	private String validationQuery;

	@Value("${spring.druid.datasource.testWhileIdle}")
	private boolean testWhileIdle;

	@Value("${spring.druid.datasource.testOnBorrow}")
	private boolean testOnBorrow;

	@Value("${spring.druid.datasource.testOnReturn}")
	private boolean testOnReturn;

	@Value("${spring.druid.datasource.poolPreparedStatements}")
	private boolean poolPreparedStatements;

	@Value("${spring.druid.datasource.maxPoolPreparedStatementPerConnectionSize}")
	private int maxPoolPreparedStatementPerConnectionSize;

	@Value("${spring.druid.datasource.filters}")
	private String filters;

	@Value("${spring.druid.datasource.connectionProperties}")
	private String connectionPropertiesStr;

	@Value("${spring.druid.datasource.useGlobalDataSourceStat}")
	private boolean useGlobalDataSourceStat;

	@Bean(name = "dataSource")
	public DataSource dataSource() throws SQLException {
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setDriverClassName(sprDriverClass);
		dataSource.setUrl(sprUrl);
		dataSource.setUsername(sprUser);
		dataSource.setPassword(sprPassword);
		dataSource.setInitialSize(initialSize);
		dataSource.setMinIdle(minIdle);
		dataSource.setMaxActive(maxActive);
		dataSource.setMaxWait(maxWait);
		dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
		dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
		if (validationQuery != null && !"".equals(validationQuery)) {
			dataSource.setValidationQuery(validationQuery);
		}
		dataSource.setTestWhileIdle(testWhileIdle);
		dataSource.setTestOnBorrow(testOnBorrow);
		dataSource.setTestOnReturn(testOnReturn);
		if (poolPreparedStatements) {
			dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
		}
		//影响批量操作
//		dataSource.setFilters(filters);
		List<Filter> filters = new ArrayList<>();
        filters.add(wallFilter);
        dataSource.setProxyFilters(filters);
		if (connectionPropertiesStr != null && !"".equals(connectionPropertiesStr)) {
			Properties connectProperties = new Properties();
			String[] propertiesList = connectionPropertiesStr.split(";");
			for (String propertiesTmp : propertiesList) {
				String[] obj = propertiesTmp.split("=");
				String key = obj[0];
				String value = obj[1];
				connectProperties.put(key, value);
			}
			dataSource.setConnectProperties(connectProperties);
		}
		dataSource.setUseGlobalDataSourceStat(useGlobalDataSourceStat);
		return dataSource;
	}

	@Bean(name = "sqlSessionFactory")
	public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);// 指定数据源(这个必须有，否则报错)

		// mapper处理
		org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
		configuration.setMapUnderscoreToCamelCase(true);
		bean.setConfiguration(configuration);

		return bean.getObject();
	}

	@Bean(name = "sqlSessionTemplate")
	public SqlSessionTemplate sqlSessionTemplate(
			@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
		return new SqlSessionTemplate(sqlSessionFactory);
	}
	
	@Autowired
	WallFilter wallFilter;

    @Bean(name = "wallConfig")
    WallConfig wallFilterConfig(){
        WallConfig wc = new WallConfig ();
        wc.setMultiStatementAllow(true);
        return wc;
    }

    @Bean(name = "wallFilter")
    @DependsOn("wallConfig")
    WallFilter wallFilter(WallConfig wallConfig){
        WallFilter wfilter = new WallFilter ();
        wfilter.setConfig(wallConfig);
        return wfilter;
    }
}
